package test.consumer;

import java.util.*;

import com.google.code.jdde.event.AdviseRequestEvent;
import com.google.code.jdde.event.AdviseStartEvent;
import com.google.code.jdde.event.AdviseStopEvent;
import com.google.code.jdde.event.ConnectEvent;
import com.google.code.jdde.misc.ClipboardFormat;
import com.google.code.jdde.server.*;
import com.google.code.jdde.server.event.ConnectionAdapter;
import com.google.code.jdde.server.event.TransactionAdapter;

import com.prm.excelserver.protobuf.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class ExcelServer {
	private final String service;
	private final String topic;
	private ArrayList<String> itemArray;
	private ExcelServerProtobuf.Instrument instMsg;
	private ExcelServerProtobuf.trade tradeMsg;
	private DdeServer server;
	public double startValue = 30.0;
	
	public CountDownLatch latch;
	public ExcelServer(final String service, final String topic, final String[] itemArray, CountDownLatch latch) {
		this.service = service;
		this.topic = topic;
		this.itemArray = new ArrayList<String>();
		this.latch = latch;
		
		for (String item : itemArray) {
			this.itemArray.add(item);
		}
		
		server = new DdeServer(0);
		server.registerService(service);
		server.setConnectionListener(new ConnectionAdapter() {
			public boolean onConnect(ConnectEvent event) {
				if (event.getTopic().equals(topic) == false) {
					return false;
				}
				System.out.println("Client Connected");
				return true;
			}
		});
	}
	public static byte[] doubleToByteArray(double input, int size, int precision) {
	    double tempInput = input;

	    for (int i = 0; i < precision; i++) tempInput *= 10;

	    int output = (int) tempInput;
	    double outdouble = (double)output/100.0;

	    //String strOut = String.format("%0"+size+"d", output);
	    String strOut = String.format("%.2f", outdouble);

	    return strOut.getBytes();
	}
	public void ActivateServer() {
		server.setTransactionListener(new TransactionAdapter() {
			public boolean onAdviseStart(AdviseStartEvent e) {
				System.out.println("AdviseStart");
				System.out.println("topic=" + e.getConversation().getTopic() + " item=" + e.getItem() + " conv=" + e.getConversation()
						+ " formatTEXT=" + ClipboardFormat.TEXT + " getFormat=" + e.getFormat());
			/*	if (	e.getConversation()==null ||
						service != e.getConversation().getService() ||
						topic != e.getConversation().getTopic() ||
						Arrays.asList(itemArray).contains(e.getItem()) == false) { 
					//ClipboardFormat.TEXT != e.getFormat()) {
					return false;
				}
			*/	
				//if ((Arrays.asList(itemArray).contains(e.getItem())) == false) {
				if (ClipboardFormat.TEXT.getValue() != e.getFormat().getValue()) {
					return false;
				}
				System.out.println("AdviseStart recieved... call postAdvise");
				latch.countDown();
				return true;
			}
			public byte[] onAdviseRequest(AdviseRequestEvent e) {
				System.out.println("AdviseRequest");
				System.out.println("topic=" + e.getConversation().getTopic() + " item=" + e.getItem());
			/*	if (	e.getConversation()==null ||
						service != e.getConversation().getService() ||
						topic != e.getConversation().getTopic() ||
						Arrays.asList(itemArray).contains(e.getItem()) == false) { 
					//ClipboardFormat.TEXT != e.getFormat()) {
					return null;
				}
			*/	
//				try {
					if (topic == "Instrument") {
						System.out.println("Instrument msg: " + e.getItem());
						return doubleToByteArray(instMsg.getBestBid(), 2, 2);
						//startValue += 0.3;
						//String retStr = new String(Double.toString(startValue));
						//return retStr.getBytes();
						/*Object instMem = ExcelServerProtobuf.class.getField("getBestBid").get(instMsg);
						
						
						
						if (instMem instanceof String) {
							String instMemString = (String) instMem;
							return instMemString.getBytes();
						} else if (instMem instanceof Integer) {
							Integer instMemInteger = (Integer) instMem;
							return new byte[]{instMemInteger.byteValue()};
						} else if (instMem instanceof Boolean) {
							Boolean instMemBoolean = (Boolean) instMem;
							return instMemBoolean.toString().getBytes();
						} else if (instMem instanceof Double) {
							Double instMemDouble = (Double) instMem;
							return new byte[] {instMemDouble.byteValue()};
						}
						*/
					} else if (topic == "Trade") {
						System.out.println("Trade msg: " + e.getItem());
						return doubleToByteArray(tradeMsg.getPrice(), 2, 2);
/*						Object tradeMem = ExcelServerProtobuf.class.getField(e.getItem()).get(tradeMsg);
						System.out.println("Trade msg: " + e.getItem());
						if (tradeMem instanceof String) {
							String tradeMemString = (String) tradeMem;
							return tradeMemString.getBytes();
						} else if (tradeMem instanceof Integer) {
							Integer tradeMemInteger = (Integer) tradeMem;
							return new byte[]{tradeMemInteger.byteValue()};
						} else if (tradeMem instanceof Boolean) {
							Boolean tradeMemBoolean = (Boolean) tradeMem;
							return tradeMemBoolean.toString().getBytes();
						} else if (tradeMem instanceof Double) {
							Double tradeMemDouble = (Double) tradeMem;
							return new byte[] {tradeMemDouble.byteValue()};
						}
*/
					} else {
						return instMsg.toByteArray();
					}
/*				} catch (NoSuchFieldException error) {
					System.out.println(error.toString());
					return null;
				} catch (IllegalAccessException error) {
					System.out.println(error.toString());
					return null;
				}
				return new byte[]{1,2,3};
*/			}
			@Override
			public void onAdviseStop(AdviseStopEvent e) {
				if (	e.getConversation()==null ||
						service != e.getConversation().getService() ||
						topic != e.getConversation().getTopic() ||
						Arrays.asList(itemArray).contains(e.getItem()) == false) { 
					//ClipboardFormat.TEXT != e.getFormat()) {
					return;
				}
				System.out.println("AdviseStop");
			}
		});
	}
	
	public void setInstMsg(ExcelServerProtobuf.Instrument instMsg) {
		this.instMsg = instMsg;
	}
	public void setTradeMsg(ExcelServerProtobuf.trade tradeMsg) {
		this.tradeMsg = tradeMsg;
	}
	public void runPostAdviseAllItems(String topic) {
		System.out.println("runPostAdvise: topic=" + topic);
		server.postAdvise(topic, (topic=="Instrument")? "best_bid" : "price");
		/*
		for (String item : itemArray) {
			System.out.print(item + " ");
			server.postAdvise(topic, item);	
		}
		*/
		System.out.println(" ");
	}
}
